package com.yangff.controller;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yangff.anno.LogExecuteTime;
import com.yangff.entity.admin.entity.Admin;
import com.yangff.entity.admin.entity.dto.AdminDTO;
import com.yangff.entity.dto.AccountDTO;
import com.yangff.entity.user.entity.User;
import com.yangff.entity.user.entity.dto.UserDTO;
import com.yangff.entity.user.entity.vo.UserVo;
import com.yangff.entity.vo.JwtVo;
import com.yangff.entity.vo.ResultVo;
import com.yangff.service.IUserService;
import com.yangff.utils.MathUtil;
import com.yangff.utils.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.security.NoSuchAlgorithmException;
import java.util.List;

/**
 * <p>
 * 存储用户基本信息 前端控制器
 * </p>
 *
 * @author yangff
 * @since 2025-01-14
 */
@LogExecuteTime
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
@Slf4j
public class UserController {
    private final IUserService userService;


    @PostMapping("/login")
    public JwtVo login(@RequestBody AccountDTO accountDTO) throws Exception {
        return userService.login(accountDTO);
    }

    //增
    @Transactional(rollbackFor = Exception.class)
    @CachePut(cacheNames = "user", key = "#user.account")
    @PostMapping("/register")
    public UserVo saveUser(@RequestBody User user) throws NoSuchAlgorithmException {
        if(user.getPassword() != null) user.setPassword(MathUtil.hashWithSHA256(user.getPassword()));
        if(user.getPaymentPassword() != null) user.setPaymentPassword(MathUtil.hashWithSHA256(user.getPaymentPassword()));
        user.setStatus(1);
        user.setFluidMoney(10000.0);
        userService.save(user);
        return BeanUtil.copyProperties(user, UserVo.class);
    }

    //获取所有用户
    @GetMapping
    public List<User> selectUser() {
        return userService.list();
    }

    @GetMapping("/page")
    public Page<User> selectUserPage(@PageableDefault Pageable pageable)
    {
        return userService.page(new Page<>(pageable.getPageNumber() + 1,pageable.getPageSize()));
    }


    //按照账户查询用户信息
    @GetMapping("/{account}")
    @Cacheable(cacheNames = "user",key = "#account")
    public UserVo getUserByAccount(@PathVariable String account)
    {
        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getAccount,account));
        UserVo userVo = BeanUtil.copyProperties(user, UserVo.class);
        return userVo;
    }

    //@CacheEvict(cacheNames = "user",key = "#account")
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "user",key = "#account")
    @DeleteMapping("/{account}")
    public ResultVo deleteUserByAccount(@PathVariable String account)
    {
        userService.remove(new LambdaQueryWrapper<User>().eq(User::getAccount,account));

        return ResultVo.success();
    }


    @Transactional(rollbackFor = Exception.class)
    @CachePut(cacheNames = "user",key = "#userDTO.account")
    @PutMapping
    public UserVo updateUserByAccount(@RequestBody UserDTO userDTO) {
        User user = userService.updateUserByAccount(userDTO);
        userService.update(user,new LambdaUpdateWrapper<User>().eq(User::getAccount,userDTO.getAccount()));
        return BeanUtil.copyProperties(user, UserVo.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @CachePut(cacheNames = "user",key = "#userDTO.account")
    @PutMapping("/money")
    public UserVo updateUserFluidMoneyByAccount(@RequestBody UserDTO userDTO) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getAccount, userDTO.getAccount())
                .setSql("fluid_money = fluid_money - " + userDTO.getChangeMoney());
        userService.update(updateWrapper);

        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getAccount,userDTO.getAccount()));

        return BeanUtil.copyProperties(user, UserVo.class);
    }


    @Transactional(rollbackFor = Exception.class)
    @CachePut(cacheNames = "user",key = "#userDTO.account")
    @PutMapping("/reset-status")
    public UserVo updateUserStatusByAccount(@RequestBody UserDTO userDTO) {

        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getAccount,userDTO.getAccount())
                .set(User::getStatus,userDTO.getStatus());
        userService.update(updateWrapper);


        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getAccount,userDTO.getAccount()));

        return BeanUtil.copyProperties(user, UserVo.class);
    }

    //单独改密码
    @PutMapping("/resetPassword")
    @CachePut(cacheNames = "user",key = "#userDTO.account")
    public UserVo updateAdminPassword(@RequestBody UserDTO userDTO) throws NoSuchAlgorithmException {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getAccount,userDTO.getAccount())
                .set(User::getPassword,MathUtil.hashWithSHA256(userDTO.getPassword()));
        userService.update(updateWrapper);

        //更新redis
        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getAccount,userDTO.getAccount()));

        return BeanUtil.copyProperties(user, UserVo.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @CachePut(cacheNames = "user",key = "#userDTO.account")
    @PutMapping("/resetPaymentPassword")
    public UserVo updateAdminPaymentPassword(@RequestBody UserDTO userDTO) throws NoSuchAlgorithmException {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getAccount,userDTO.getAccount())
                .set(User::getPaymentPassword,MathUtil.hashWithSHA256(userDTO.getPaymentPassword()));
        userService.update(updateWrapper);

        //更新redis
        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getAccount,userDTO.getAccount()));
        return BeanUtil.copyProperties(user, UserVo.class);
    }




}
